package cn.caplike.demo.nio._2017;

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * 简介：MappedByteBuffer
 *
 * @author 李珂 2017年11月24日 下午3:45:57
 */
public class MappedByteBufferTest02 {
	private static int LENGTH = 0x2FFFFFF;
	private static StandardOpenOption[] OPTION_ARR = {StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.DELETE_ON_CLOSE};
	private static String PATH_PREFIX = "data/mappedbytebuffer/";
	/**
	 * 测试用例
	 */
	private static Tester[] testerArr = {new Tester("Stream RW") {
		public void test() {
			try (FileInputStream fis = new FileInputStream(PATH_PREFIX + "a.txt");
				 DataInputStream dis = new DataInputStream(fis);
				 FileOutputStream fos = new FileOutputStream(PATH_PREFIX + "a.txt");
				 DataOutputStream dos = new DataOutputStream(fos)) {

				byte b = (byte) 0;
				for (int i = 0; i < LENGTH; i++) {
					dos.writeByte(b);
					dos.flush();
				}
				while (dis.read() != -1) {
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}, new Tester("Mapped RW") {
		public void test() {
			try (FileChannel channel = FileChannel.open(Paths.get(PATH_PREFIX + "b.txt"), OPTION_ARR)) {
				MappedByteBuffer mapBuffer = channel.map(FileChannel.MapMode.READ_WRITE, 0, LENGTH);
				for (int i = 0; i < LENGTH; i++) {
					mapBuffer.put((byte) 0);
				}
				mapBuffer.flip();
				while (mapBuffer.hasRemaining()) {
					mapBuffer.get();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}, new Tester("Mapped PRIVATE") {
		public void test() {
			try (FileChannel channel = FileChannel.open(Paths.get(PATH_PREFIX + "c.txt"), OPTION_ARR)) {
				MappedByteBuffer mapBuffer = channel.map(FileChannel.MapMode.PRIVATE, 0, LENGTH);
				for (int i = 0; i < LENGTH; i++) {
					mapBuffer.put((byte) 0);
				}
				mapBuffer.flip();
				while (mapBuffer.hasRemaining()) {
					mapBuffer.get();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}};

	/**
	 * 简介：准备文件
	 *
	 * @throws IOException
	 * @author 李珂 2017年11月24日 下午4:53:35
	 */
	private static void createTestFiles() throws IOException {
		Files.createFile(Paths.get(PATH_PREFIX + "a.txt"));
		Files.createFile(Paths.get(PATH_PREFIX + "b.txt"));
		Files.createFile(Paths.get(PATH_PREFIX + "c.txt"));
	}

	/**
	 * 简介：entry
	 *
	 * @param args
	 * @throws IOException
	 * @author 李珂 2017年11月24日 下午5:02:26
	 */
	public static void main(String[] args) throws IOException {
		createTestFiles();
		for (Tester tester : testerArr) {
			new Thread(new MappedByteBufferTest02().new TheThread(tester)).start();
		}
	}

	/**
	 * 简介：抽象静态内部类
	 *
	 * @author 李珂 2017年11月24日 下午4:46:59
	 */
	private abstract static class Tester {
		private String name;

		public Tester(String name) {
			this.name = name;
		}

		public void runTest() {
			long start = System.currentTimeMillis();
			test();
			System.out.println(this.name + ": " + (System.currentTimeMillis() - start) / 60 + "s");
		}

		public abstract void test();
	}

	/**
	 * 简介：运行测试的线程
	 *
	 * @author 李珂 2017年11月24日 下午4:46:22
	 */
	private class TheThread implements Runnable {
		private Tester tester;

		public TheThread(Tester tester) {
			this.tester = tester;
		}

		/*
		 * (non-Javadoc)
		 *
		 * @see java.lang.Runnable#run()
		 */
		@Override
		public void run() {
			this.tester.runTest();
		}
	}

}
